home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 2.toast / pc / sample code / quicktime / quicktimeintro / sequence grabbing / start code / sequencegrab.c
Encoding:
C/C++ Source or Header  |  2000-10-06  |  9.5 KB  |  431 lines

  1. /*    Sequence Grabber Lab
  2.  
  3.     This sample shows how to use a sequence grabber component to preview and record captured data.
  4.     The example also demonstrates how to set up VideoBottlenecks and draw over top of captured data
  5.     during the GrabFrameComplete callback.
  6. */
  7.     
  8. #include "SequenceGrab.h"
  9.  
  10. // globals
  11. // ------------------------
  12. BitMap screenBits;
  13. ICMAlignmentProcRecord    apr;
  14.  
  15. // functions
  16. // ------------------------
  17.  
  18. // GrabFrameCompleteProc
  19. // This is where we draw text over the captured frame
  20. pascal ComponentResult GrabFrameCompleteProc(SGChannel sgChan, short nBufferNum, Boolean *pbDone, long lRefCon)
  21. {
  22.     ComponentResult        err = noErr;
  23.     
  24.     // call the default grab-complete function
  25.     
  26. // Step 1.
  27. // Insert "SGGrabFrameComplete.clp" here
  28.      
  29.      // if the frame is done, draw some text over it
  30.     if (*pbDone) {
  31.         CGrafPtr        pOldPort;
  32.         CGrafPtr        pTempPort = (CGrafPtr)lRefCon;
  33.         GDHandle        hghOldDevice;
  34.         PixMapHandle    hPixMap, hOldPixMap;
  35.         Rect            rectBuffer;
  36.  
  37.         // set to our temporary port
  38.         GetGWorld(&pOldPort, &hghOldDevice);
  39.         SetGWorld(pTempPort, NULL);
  40.  
  41.         // obtain information about a buffer that has
  42.         // been passed to your callback function
  43.         
  44. // Step 2.
  45. // Insert "SGGetBufferInfo.clp" here
  46.         
  47.         if (err == noErr) {
  48.             // set up to draw into this buffer
  49.             hOldPixMap = GetPortPixMap(pTempPort);
  50.             SetPortPix(hPixMap);
  51.  
  52.             // draw some text into the buffer
  53.             TextSize(10);
  54.             TextMode(srcXor);
  55.             MoveTo(rectBuffer.left + 5, rectBuffer.bottom - 5);
  56.             DrawString("\pGrabFrameCompleteProc");
  57.             
  58.             // restore temporary port
  59.             SetPortPix(hOldPixMap);
  60.         }
  61.  
  62.         // restore old ports
  63.         SetGWorld(pOldPort, hghOldDevice);
  64.     }
  65.     
  66.     return err;
  67. }
  68.  
  69. // SetupVideoBottlenecks
  70. // This function initializes the video bottleneck procedure so the sequence grabber
  71. // will call us when a frame has been captured. There are nine bottleneck procs.
  72. /*         struct VideoBottles {
  73.             short                           procCount;
  74.             SGGrabBottleUPP                 grabProc;
  75.             SGGrabCompleteBottleUPP         grabCompleteProc;
  76.             SGDisplayBottleUPP              displayProc;
  77.             SGCompressBottleUPP             compressProc;
  78.             SGCompressCompleteBottleUPP     compressCompleteProc;
  79.             SGAddFrameBottleUPP             addFrameProc;
  80.             SGTransferFrameBottleUPP        transferFrameProc;
  81.             SGGrabCompressCompleteBottleUPP  grabCompressCompleteProc;
  82.             SGDisplayCompressBottleUPP      displayCompressProc;
  83.         }
  84. */
  85. OSErr SetupVideoBottlenecks(SGChannel sgchanVideo, CGrafPtr pTempPort)
  86. {
  87.     OSErr    err = noErr;
  88.  
  89.     // set the value of a reference constant that is passed to the callback functions
  90.     err = SGSetChannelRefCon(sgchanVideo, (long)pTempPort);
  91.     
  92.     if (err == noErr) {
  93.         VideoBottles    vb;
  94.  
  95.         // get the current bottlenecks
  96.  
  97. // Step 1.
  98. // Insert "SGGetVideoBottlenecks.clp" here
  99.         
  100.         if (err == noErr) {
  101.             RgnHandle    theRgn = NewRgn();
  102.             
  103.             // add our GrabFrameComplete function
  104.  
  105. // Step 2.
  106. // Insert "SGSetVideoBottlenecks" here
  107.             
  108.             // set up the temporary port with
  109.             // a wide open visible and clip region...
  110.             // so that you can use it in any video buffer
  111.             SetRectRgn(theRgn, -32000, -32000, 32000, 32000);
  112.             SetPortVisibleRegion(pTempPort, theRgn);
  113.             SetPortClipRegion(pTempPort, theRgn);
  114.             
  115.             // tell QuickDraw about the changes
  116.             PortChanged((GrafPtr)pTempPort);
  117.             
  118.             DisposeRgn(theRgn);
  119.         }
  120.     }
  121.  
  122.     return err;
  123. }
  124.  
  125. // MakeSequenceGrabber
  126. // Open the default sequence graber component and initialize it
  127. SeqGrabComponent MakeSequenceGrabber(WindowPtr pMacWnd)
  128. {
  129.     SeqGrabComponent    seqGrab = NULL;
  130.     long                flags = 0;
  131.     OSErr                err = noErr;
  132.  
  133.     // open up the default sequence grabber
  134.     seqGrab = OpenDefaultComponent(SeqGrabComponentType, 0);
  135.     
  136.     if (seqGrab != NULL) { 
  137.         // initialize the default sequence grabber component
  138.  
  139. // Step 1.
  140. // Insert "SGInitialize.clp" here
  141.  
  142.     }
  143.  
  144.     if (err && (seqGrab != NULL)) {
  145.         // clean up on failure
  146.         CloseComponent(seqGrab);
  147.         seqGrab = NULL;
  148.     }
  149.     return seqGrab;
  150. }
  151.  
  152. // MakeSequenceGrabChannels
  153. // Create the new video and sound channels and set up the channel usage
  154. void MakeSequenceGrabChannels(SeqGrabComponent seqGrab, SGChannel *sgchanVideo, SGChannel *sgchanSound, const Rect *rect, Boolean bWillRecord)
  155. {
  156.     long    lUsage;
  157.     
  158.     OSErr    err = noErr;
  159.  
  160.     // figure out the channel usage
  161.     lUsage = seqGrabPreview;        // always previewing by default
  162.     if (bWillRecord)
  163.         lUsage |= seqGrabRecord;    // are we going to record?
  164.  
  165.     // create a video channel
  166.     
  167. // Step 1.
  168. // Insert "SGNewChannel.clp" here
  169.  
  170.     if (err == noErr) {
  171.         // set boundaries for new video channel
  172.  
  173. // Step 2.
  174. // Insert "SGSetChannelBounds/Usage.clp" here
  175.         
  176.         if (err != noErr) {
  177.             // clean up on failure
  178.             SGDisposeChannel(seqGrab, *sgchanVideo);
  179.             *sgchanVideo = NULL;
  180.         }
  181.     }
  182.  
  183.     // create a sound channel
  184.     err = SGNewChannel(seqGrab, SoundMediaType, sgchanSound);
  185.     if (err == noErr) {
  186.         // set usage of new sound channel
  187.         err = SGSetChannelUsage(*sgchanSound, lUsage);
  188.         
  189.         if (err != noErr) {
  190.             // clean up on failure
  191.             SGDisposeChannel(seqGrab, *sgchanSound);
  192.             *sgchanSound = NULL;
  193.         }
  194.     }
  195. }
  196.  
  197. OSErr DoRecord(SeqGrabComponent seqGrab)
  198. {
  199.     FSSpec    theFSSpec;
  200.     Boolean isSelected, isReplacing;
  201.     OSErr                err = noErr;
  202.     
  203.     // Stop everything while the dialogs are up
  204.  
  205. // Step 1.
  206. // Insert "SGStop.clp" here
  207.     
  208.     err = PutFile("\pSave new movie file as:", "\pSequenceGrab.mov", &theFSSpec, &isSelected, &isReplacing);
  209.     if ((err = SGSetDataOutput(seqGrab, &theFSSpec, seqGrabToDisk)))
  210.         goto bail;
  211.         
  212.     // Attempt to recover the preview area obscured by dialogs
  213.     SGUpdate(seqGrab, 0);
  214.  
  215.     // Make the movie file
  216.     DeleteMovieFile(&theFSSpec);
  217.  
  218. // Step 2.
  219. // Insert "CreateMovieFile.clp here
  220.  
  221.     if (err) goto bail;
  222.         
  223.     FlushEvents(mDownMask+mUpMask,0);
  224.     
  225.     // Record!
  226.  
  227. // Step 3.
  228. // Insert "SGStartRecord.clp" here
  229.  
  230.     if (err) goto bail;
  231.  
  232.     while (!Button() && (err == noErr))
  233.     {
  234.         // give time for record
  235.         err = SGIdle(seqGrab);
  236.     }
  237.     
  238.     FlushEvents(mDownMask+mUpMask,0);
  239.  
  240.     // If we recorded until we ran out of space, then allow SGStop to be
  241.     // called to write the movie resource.  The assumption here is that the
  242.     // data output filled up but the disk has enough free space left to
  243.     // write the movie resource.
  244.     if (!((err == dskFulErr) || (err != eofErr))) {
  245.         DeleteMovieFile(&theFSSpec);
  246.         goto bail;
  247.     }
  248.         
  249.     err = SGStop(seqGrab);
  250.  
  251. bail:    
  252.     
  253.     err = SGStartPreview(seqGrab);
  254.  
  255.     return err;
  256. }
  257.  
  258. WindowRef MakeAWindow(void)
  259. {
  260.     WindowPtr        pMacWnd;
  261.     Rect            rectWnd = {0, 0, 230, 320}; //{0, 0, 480, 740};
  262.     Rect            rectBest;
  263.  
  264.     // figure out the best monitor for the window
  265.     GetBestDeviceRect(NULL, &rectBest);
  266.  
  267.     // put the window in the top left corner of that monitor
  268.     OffsetRect(&rectWnd, rectBest.left + 10, rectBest.top + 50);
  269.  
  270.     // create the window
  271.     pMacWnd = NewCWindow(NULL, &rectWnd, "\pSequence Grabber",true, kWindowDocumentProc, (WindowPtr)-1,true, 0);
  272.  
  273.     // set the port to the new window
  274.     SetPort(GetWindowPort(pMacWnd));
  275.  
  276.     return pMacWnd;
  277. }
  278.  
  279. Boolean IsQuickTimeInstalled(void) 
  280. {
  281.     OSErr    err;
  282.     long    lResult;
  283.  
  284.     err = Gestalt(gestaltQuickTime, &lResult);
  285.     return (err == noErr);
  286. }
  287.  
  288. void main(void)
  289. {
  290.     WindowRef                pMacWnd;
  291.     CGrafPtr                pTempPort;
  292.     SeqGrabComponent        seqGrab;
  293.     SGChannel                sgchanVideo, sgchanSound;
  294.     Rect                    thePortRect;
  295.     Boolean                    bDone = false;
  296.     
  297.     OSErr                    err = noErr;
  298.  
  299.     // initialize for carbon & QuickTime
  300.     InitCursor();
  301.     if ( IsQuickTimeInstalled() )
  302.         EnterMovies();
  303.     else
  304.         goto bail;
  305.         
  306.     GetQDGlobalsScreenBits( &screenBits );
  307.     
  308.     // create a window
  309.     pMacWnd = MakeAWindow();
  310.  
  311. // Step 1.
  312. // Build MakeSequenceGrabber function
  313.  
  314.     // create a sequence grabber
  315.     seqGrab = MakeSequenceGrabber(pMacWnd);
  316.     if (seqGrab == NULL)
  317.         return;
  318.  
  319. // Step 2.
  320. // Build MakeSequenceGrabChannels function
  321.  
  322.     // create the grab channels
  323.     GetPortBounds(GetWindowPort(pMacWnd), &thePortRect);
  324.     MakeSequenceGrabChannels(seqGrab, &sgchanVideo, &sgchanSound, &thePortRect, true); // true = recording
  325.  
  326. // Step 3.
  327. // Build SetupVideoBottlenecks function
  328.  
  329.     // set up a video bottleneck
  330.     // create a temporary port for drawing...
  331.     pTempPort = CreateNewPort();                 
  332.     if (sgchanVideo != NULL) {
  333.         err = SetupVideoBottlenecks(sgchanVideo, pTempPort);
  334.     }
  335.     
  336.     // start the sequence grabber preview
  337.  
  338. // Step 4.
  339. // Insert "SGStartPreview.clp" here
  340.  
  341.     if (err) goto bail;
  342.  
  343.     while (!bDone) {
  344.         short        nPart;
  345.         WindowRef    pWhichWnd;
  346.         EventRecord    er; 
  347.  
  348.         GetNextEvent(everyEvent, &er);
  349.  
  350.         switch (er.what) {
  351.         case nullEvent:
  352.             // give the sequence grabber time
  353.                             
  354. // Step 5.
  355. // Insert "SGIdle.clp" here
  356.             
  357.             if (err != noErr)
  358.                 bDone = true;
  359.             break;
  360.  
  361.         case updateEvt:
  362.             if (er.message == (long)pMacWnd) {
  363.                 RgnHandle updateRgn = NewRgn();
  364.                 
  365.                 GetWindowRegion(pMacWnd, kWindowUpdateRgn, updateRgn);
  366.                 
  367.                 // inform the sequence grabber of the update
  368. // Step 6.
  369. // Insert "SGUpdate.clp" here
  370.                 
  371.                 // and swallow the update event
  372.                 BeginUpdate(pMacWnd);
  373.                 EndUpdate(pMacWnd);
  374.                 
  375.                 DisposeRgn(updateRgn);
  376.             }
  377.             break;
  378.  
  379.         case mouseDown:
  380.             nPart = FindWindow(er.where, &pWhichWnd);
  381.             if (pWhichWnd == pMacWnd) {
  382.                 switch (nPart) {
  383.                 case inContent:
  384.                     if ( er.modifiers & cmdKey ) {
  385.  
  386. // Step 7.
  387. // Build DoRecord function
  388.  
  389.                         DoRecord( seqGrab );
  390.                         break;
  391.                     }
  392.                     
  393.                     // pause until mouse button is released
  394.                     SGPause(seqGrab, true);
  395.                     while (StillDown())
  396.                         ;
  397.                     SGPause(seqGrab, false);
  398.                     break;
  399.                 
  400.                 case inGoAway:
  401.                     bDone = TrackGoAway(pMacWnd, er.where);
  402.                     break;
  403.  
  404.                 case inDrag:
  405.                     if (StillDown()) {                    
  406.                         // pause when dragging window so video 
  407.                         // doesn't draw in the wrong place
  408.  
  409. // Step 8.
  410. // Insert SGPause.clp here
  411.  
  412.                     }
  413.                     break;
  414.                 
  415.                 } // switch
  416.             }
  417.             break;
  418.             
  419.         } // switch
  420.     } // while
  421.     
  422. bail:
  423.  
  424.     // clean up
  425.     if ( seqGrab ) {
  426.         SGStop(seqGrab);
  427.         CloseComponent(seqGrab);
  428.     }
  429.     if ( pMacWnd )
  430.         DisposeWindow(pMacWnd);
  431. }